package trab3;

import java.awt.*;
import java.util.*;
import java.awt.geom.*;

import sim.core.* ;
import trab3.msgs.*;

public class Main extends Simulation implements Displayable {
	
	public static final int TOTAL_NODES = 40 ;

	Main() {
		super() ;
	}

	Main init() {
	
		Gui.addItem( this) ;
		//Gui.removeItem( Network ) ;
		
		Network.setSpannerThreshold( 10.01) ;

		//Create the simulation nodes
		for( int i = 0 ; i < TOTAL_NODES ; i++ ) 
			new Node() ;

		Node masterNode = NodeDB.randomNode() ;
		
		//Initialize the simulation nodes
		for( Node i : NodeDB.nodes ) 
			i.init( masterNode.endpoint ) ;

		Set<Node> canVeto = new HashSet<Node>() ;
		while( canVeto.size() < 5 )
			canVeto.add( NodeDB.randomNode() ) ;
		
		for( Node i : canVeto )
			i.setCanVeto() ;

	//	setSimulationMaxTimeWarp(20) ;

		
		new PeriodicTask( 0, 50) {
			public void run() {
				int N = NodeDB.size() ;
				double D = Double.MIN_VALUE ; 
				for( int i = 0 ; i < N ; i++ ) {
					Node nI = NodeDB.nodes.get(i) ;
					for( int j = 0 ; j < i ; j++ ) {
						double skew = nI.currentTime() - NodeDB.nodes.get(j).currentTime() ;
						D = Math.max( D, Math.abs( skew )) ;
					}
				}
//				System.out.printf("%f : %.6f\n", Simulation.currentTime(), D) ;
				System.out.printf("%.6f\n", D) ;
			}
		};
	
		
		//Periodically, choose a node randomly to propose a color change
		//The task will execute for the first time after 2000 seconds to
		//allow the clock synchronization process to converge.
/*		new PeriodicTask(2000, 120) {
			public void run() {
				setSimulationMaxTimeWarp(20) ;
				NodeDB.randomNode().changeColor( false ) ;
			}
		} ; /**/
		
		
		System.out.println("Init complete...") ;
		return this ;
	}
	

	public static void main( String[] args ) throws Exception {
		new Main().init().start() ;
	}

	public void display(Graphics2D gu, Graphics2D gs) {
		for( Node i : NodeDB.nodes )
			i.display(gu, gs) ;		
		

		final double S = 32;
		ArrayList<ChangeColor> cce = new ArrayList<ChangeColor>(latestCCEvents) ;
	
		double x = -200, y = 950 ;

		for ( ChangeColor i : cce ) {
			
			gs.setColor( i.color);
			gs.fill( new Ellipse2D.Double( x - S/2, y - S/2, S, S));
			if( i.veto ) {
				gs.setColor( Color.black ) ;
				gs.fill( new Ellipse2D.Double( x - S/6, y - S/6, S/3, S/3));
			}
			y -= S + 1;
		}
	}
	
	static Queue<ChangeColor> latestCCEvents = new LinkedList<ChangeColor>() ;
}
